package cn.yj.common.factory;

import cn.yj.alipay.wrapper.AliPayFromExecutorExecutor;
import cn.yj.common.emums.PayFrom;
import cn.yj.common.emums.PayType;
import cn.yj.common.entity.*;
import cn.yj.common.exception.PayException;
import cn.yj.common.interfaces.IPayFromExecutor;
import cn.yj.wx.pay.wrapper.WechatPayExecutor;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;

import java.util.Map;

/**
 * @author 永健
 * @since 2022-02-18 11:53
 */
public class PayTypeFactory {

    private PayType payType;

    private PayFrom payFrom;

    private IPayFromExecutor iPayFromExecutor;

    private PayTypeFactory(PayType payType, PayFrom payFrom) {
        this.payType = payType;
        this.payFrom = payFrom;
        this.selectExecutor();
    }

    public IPayFromExecutor getPayFromExecutor() {
        return this.iPayFromExecutor;
    }

    public static PayTypeFactory build(PayType payType, PayFrom payFrom) {
        return new PayTypeFactory(payType, payFrom);
    }

    public static PayTypeFactory build(PayType payType) {
        return new PayTypeFactory(payType, null);
    }


    public PayTypeFactory selectExecutor() {
        switch (payType) {
            case ALIPAY:
                this.iPayFromExecutor = AliPayFromExecutorExecutor.getInstance();
                break;
            default:
                this.iPayFromExecutor = WechatPayExecutor.getInstance();
                break;
        }
        return this;
    }

    public <T extends PayResult> T underOrder(Map<String, Object> params) throws PayException {
        return (T) this.iPayFromExecutor.underOrder(this.payFrom, getRequestObject(params));
    }

    public JSONObject refund(RefundParams params) throws PayException {
        Object refund = this.iPayFromExecutor.refund(params);
        Gson gson = new Gson();
        return gson.fromJson(gson.toJson(refund), JSONObject.class);
    }

    public PayOrder queryOrder(String outTradeNo) throws PayException {
        return (PayOrder) this.iPayFromExecutor.queryOrder(outTradeNo);
    }

    public PayRefundOrder queryRefundOrder(RefundQueryParams params) throws PayException {
        return  this.iPayFromExecutor.queryRefundOrder(params);
    }

    private Object getRequestObject(Map<String, Object> params) {
        return this.iPayFromExecutor.getRequestParams(payFrom, params);
    }
}
